/*
    浅拷贝
    浅拷贝只复制对象的第一层属性。如果属性是基本类型（如 number、string、boolean），则直接复制值；
            如果属性是引用类型（如 object、array），则复制的是其引用，而不是创建新的对象。
            修改拷贝后对象的嵌套对象，会影响原对象
*/

//浅拷贝的实现方式：
//1. Object.assign()
const obj1 = { a: 1, b: { c: 2 } }
const obj2 = Object.assign({}, obj1)
obj2.b.c = 3
console.log(obj1.b.c) //3.原对象也被修改

//2. 展开运算符
const obj3 = { a: 1, b: { c: 2 } }
const obj4 = { ...obj3 }
obj4.b.c = 3
console.log(obj3.b.c) //3.原对象也被修改

//3.Array.prototype.slice()（仅适用于数组）
const arr1 = [1, { a: 2 }];
const arr2 = arr1.slice();
arr2[1].a = 3;
console.log(arr1[1].a); // 3

//4.for循环
const obj = { a: 1, b: { c: 2 } };
const copyObj = {}
for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
        copyObj[key] = obj[key]
    }
}
obj.b.c = 4
console.log(copyObj.b.c) //4.原对象也被修改

//这里面性能最高的是for循环  //直接操作索引，没有函数调用开销。避免了高阶函数（如 map、forEach）的回调函数调用成本。
//对于数据量小于1000 其实差别不大，虽然map、filter等也可以实现，但是不推荐，不符合语义化


//深拷贝会 递归地复制对象的所有层级，包括嵌套的对象和数组，生成一个全新的对象。修改拷贝后的对象不会影响原对象。
//实现方式
//1.JSON.parse(JSON.stringify(obj)) 简单快捷，适用于大多数场景 
//缺点 ：无法处理函数、undefined、Symbol、Date、RegExp 等特殊类型。
//会忽略 undefined 和函数。
//不能处理循环引用（会报错） a引用b b也引用a
const obj6 = { a: 1, b: { c: 2 }, d: new Date(), e: undefined, f: () => { } };
const obj7 = JSON.parse(JSON.stringify(obj1));
console.log(obj7.d) //undefined  无法处理函数、undefined、Symbol、Date、RegExp 等特殊类型。
console.log(obj7)
obj7.b.c = 3;
console.log(obj6.b.c); // 2，未受影响           

//2.手动递归实现
function deepClone(obj, visited = new WeakMap()) {
  // 处理 null 和 undefined
  if (obj == null) return obj;

  // 处理 Date
  if (obj instanceof Date) return new Date(obj);

  // 处理 RegExp
  if (obj instanceof RegExp) return new RegExp(obj);

  // 处理基本类型和函数
  if (typeof obj !== 'object') return obj;

  // 防止循环引用
  if (visited.has(obj)) {
    return visited.get(obj);
  }

  // 创建新对象或数组
  const clone = Array.isArray(obj) ? [] : {};
  visited.set(obj, clone);

  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      clone[key] = deepClone(obj[key], visited);
    }
  }

  return clone;
}

// 使用示例
const obj10 = { a: 1, b: { c: 2 } };
const obj20 = deepClone(obj10);
obj20.b.c = 3;
console.log(obj10.b.c); // 2

//3.使用lodash _.cloneDeep()